Skip to content

feat: add deploy-promote workflow for one-click branch promotion#3199

Open
yodem wants to merge 9 commits intomasterfrom
feature/deploy-promote-workflow
Open

feat: add deploy-promote workflow for one-click branch promotion#3199
yodem wants to merge 9 commits intomasterfrom
feature/deploy-promote-workflow

Conversation

@yodem
Copy link
Copy Markdown
Collaborator

@yodem yodem commented Mar 30, 2026

Summary

  • Adds environment-gated promotion jobs to deploy-static.yaml — after staging deploy on push to master, two manual "Review deployments" buttons appear for promoting to preprod and prod
  • Adds promotion-gate.yaml — a required status check that enforces allowed merge paths (blocks invalid PRs before merge)
  • Shared changelog script (build/ci/generate-promotion-pr.sh) auto-generates PR body with commit counts
  • Slack notification on prod promotion

How it works

Promotion flow (deploy-static.yaml)

  1. PR merges to master → deploy-static runs: detect → release → deploy to staging
  2. Two jobs appear as pending: "Promote: master → preprod" and "Promote: preprod → prod"
  3. Developer clicks "Review deployments" in the Actions UI → approves
  4. Job runs build/ci/generate-promotion-pr.sh which creates a PR with auto-generated changelog
  5. Merging that PR triggers another deploy-static run for the target environment

Branch protection (promotion-gate.yaml)

  • Runs on PRs targeting preprod or prod
  • Enforces: preprod ← only master or hotfix/*; prod ← only preprod or hotfix/*
  • Blocks the merge button if the source branch is wrong

Setup needed (manual steps)

1. Create GitHub Environments

Go to repo Settings → Environments and create:

  • promote-preprod — add required reviewers (team members who can approve preprod deploys)
  • promote-prod — add required reviewers (team members who can approve prod deploys)

2. Add required status check

Go to repo Settings → Branches → Branch protection rules:

  • For preprod branch: enable "Require status checks" → add "Promotion Gate"
  • For prod branch: enable "Require status checks" → add "Promotion Gate"
  • For both: disable direct pushes (require PRs only)

3. Add Slack webhook secret

  • Add SLACK_DEPLOY_WEBHOOK secret in repo Settings → Secrets (for prod promotion Slack notifications)

Files changed

File Description
.github/workflows/deploy-static.yaml Added 2 environment-gated promote jobs after trigger-deploy
.github/workflows/promotion-gate.yaml New workflow — validates PR source branch on PRs to preprod/prod
build/ci/generate-promotion-pr.sh New shared script — generates changelog + creates PR

Test plan

  • Verify promotion-gate.yaml passes on PR from masterpreprod
  • Verify promotion-gate.yaml fails on PR from feature/*preprod
  • Verify promotion-gate.yaml passes on PR from hotfix/*prod
  • Merge a PR to master → confirm promote jobs appear as pending in Actions
  • Click "Review deployments" on promote-to-preprod → confirm PR is created
  • Verify Slack notification fires on prod promotion
  • Verify script handles empty diff (no commits between branches) gracefully

🤖 Generated with Claude Code

yodem and others added 9 commits March 30, 2026 13:53
Adds a GitHub Actions workflow_dispatch that automates creating PRs
for master→preprod and preprod→prod promotions with auto-generated
changelogs and Slack notifications for prod deploys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removes standalone deploy-promote.yml and adds two manual jobs
(promote-changelog, promote-create-pr) to the existing Continuous
workflow via workflow_dispatch. Supports preprod and prod targets
with auto-changelog and Slack notifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix concurrency group to avoid cancelling promote jobs on concurrent pushes
- Guard jest-tests from running on workflow_dispatch events
- Fix PR body heredoc indentation that broke markdown rendering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two manual jobs now appear in every push-to-master workflow run:
- "Promote: master → preprod" (gated by promote-preprod environment)
- "Promote: preprod → prod" (gated by promote-prod environment)

Developers click "Review deployments" in the Actions UI to approve.
Each job generates a changelog and creates a PR automatically.
Prod promotions also post to Slack.

Requires creating "promote-preprod" and "promote-prod" environments
in repo Settings → Environments with required reviewers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Promotion jobs belong in deploy-static.yaml since that's the workflow
that runs on push to master/preprod/prod. After the staging deploy
completes (detect → release → update-state → trigger-deploy),
two environment-gated jobs appear:

  - "Promote: master → preprod" (gated by promote-preprod env)
  - "Promote: preprod → prod" (gated by promote-prod env)

Developers click "Review deployments" to approve, then the job
creates a PR with auto-generated changelog. Prod also sends Slack.

Reverts continuous.yaml to its original state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a branch-protection job that runs before detect and enforces:
- preprod: only accepts merges from master
- prod: only accepts merges from preprod, unless the actor is in
  the HOTFIX_ALLOWED_USERS secret (comma-separated usernames)
- master: no restriction
- [skip ci] deploy state commits are always allowed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moves branch protection from deploy-static (post-push, too late) to
a separate promotion-gate.yaml that runs on PRs targeting preprod/prod.

Rules:
  - preprod: only accepts PRs from master
  - prod: only accepts PRs from preprod (or hotfix users)

This should be set as a required status check in GitHub branch protection
for preprod and prod branches — prevents the merge button from being
available when the source branch is wrong.

Hotfix users are configured via HOTFIX_ALLOWED_USERS secret
(comma-separated GitHub usernames).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates promotion gate per team feedback:
- preprod accepts: master, hotfix/*
- prod accepts: preprod, hotfix/*
- Removed per-user hotfix check (HOTFIX_ALLOWED_USERS) — who can
  approve is controlled by GitHub environment reviewers instead

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract changelog + PR creation to build/ci/generate-promotion-pr.sh
  (DRYs up the two promote jobs in deploy-static.yaml)
- Handle empty commits: skips PR creation when branches are identical
- Add merge_group trigger to promotion-gate.yaml for merge queue support
- Slack notification now also skips on no-changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant